# -*- coding: utf-8 -*-
import logging
from common import slave
from common.notification.model import *
from common.utils.db import (
    paginate, parse_query_dct, get_orderby, get_count,
    generate_filter, upsert, delete, list_object, get)
from common.utils.decorator import sql_wrapper, slave_wrapper
from common.cache import redis_cache
from common.account.db import account

_LOGGER = logging.getLogger(__name__)


@sql_wrapper
def get_lasted_notification(user_id, notify_type):
    query = Notification.query.filter(Notification.notify_type == notify_type)
    if notify_type in USER_NOTIFY_TYPES:
        if not user_id:
            return None
        query = query.filter(Notification.user_id == user_id)
    else:
        query = query.filter(Notification.status == NOTIFY_STATUS.RELEASED)
    notify = query.order_by(Notification.id.desc()).first()
    return notify


@sql_wrapper
def read_notify(user_id, notify_id):
    notify = Notification.query.with_for_update().filter(
        Notification.id == notify_id).filter(Notification.read == 0).first()
    if not notify:
        return

    if notify.user_id == user_id:
        notify.read = True
        notify.save()
        return notify.notify_type
    else:
        redis_cache.add_read_sys_notify(user_id, notify_id)


@slave_wrapper
def get_notifications(user_id, notify_type, limit, offset):
    query = slave.session.query(Notification).filter(Notification.notify_type == notify_type)
    if notify_type in USER_NOTIFY_TYPES:
        if not user_id:
            return []
        query = query.filter(Notification.user_id == user_id)
    else:
        query = query.filter(Notification.status == NOTIFY_STATUS.RELEASED)
    query = query.order_by(Notification.id.desc())
    if limit > 0:
        query = query.limit(limit)
    if offset > 0:
        query = query.offset(offset)

    notify_list = []
    for each in query:
        if notify_type in SYS_NOTIFY_TYPES:
            if redis_cache.has_read_sys_notify(user_id, each.id):
                each.read = True
        notify_list.append(each)

    return notify_list


@sql_wrapper
def get_notify_by_id(notify_id):
    notify = Notification.query.filter(Notification.id == notify_id).first()
    return notify


@sql_wrapper
def create_user_notification(user_id, notify_type, content):
    notify = Notification()
    notify.user_id = user_id
    notify.notify_type = notify_type
    notify.content = content
    notify.save()
    return notify


@sql_wrapper
def list_notification(query_dct, sys_type=False, created_by=None):
    _LOGGER.info("list_notification {} {} {}".format(query_dct, sys_type, created_by))
    query_dct = parse_query_dct(query_dct, Notification)
    if sys_type:
        query = Notification.query.filter(generate_filter(query_dct, Notification)).filter(
            Notification.notify_type.in_(SYS_NOTIFY_TYPES))
    else:
        query = Notification.query.filter(generate_filter(query_dct, Notification))

    if created_by:
        query = Notification.query.filter(Notification.created_by == created_by)
    total_count = get_count(query)
    orderby = get_orderby(query_dct.get('$orderby'), Notification)
    if orderby is not None:
        query = query.order_by(orderby)

    query = paginate(query, query_dct)

    return query.all(), total_count


@sql_wrapper
def generate_sys_notification(content, notify_type, command, status=0, extend=None, expire_ts=0, user_ids=None,
                              created_by=None):
    if not user_ids:
        notification = Notification()
        notification.content = content
        notification.notify_type = notify_type
        notification.command = command
        notification.extend = extend
        notification.expire_ts = expire_ts
        notification.status = status
        notification.created_by = created_by
        notification.save()
    else:
        for user_id in user_ids:
            if not account.get_account(user_id, use_cache=True):
                _LOGGER.info(" user dont exists {}".format(user_id))
                continue
            notification = Notification()
            notification.content = content
            notification.user_id = int(user_id)
            notification.notify_type = notify_type
            notification.command = command
            notification.extend = extend
            notification.expire_ts = expire_ts
            notification.status = status
            notification.created_by = created_by
            notification.save()

    return notification.id


@sql_wrapper
def get_in_app_announcement(id):
    return get(InAppAnnouncement, id)


@sql_wrapper
def list_in_app_announcement(query_dct):
    return list_object(query_dct, InAppAnnouncement)


@sql_wrapper
def upsert_in_app_announcement(info, id=None):
    return upsert(InAppAnnouncement, info, id)


@sql_wrapper
def delete_in_app_announcement(id):
    delete(InAppAnnouncement, id)


@sql_wrapper
def update_notification(notify_id, param_dct):
    upsert(Notification, param_dct, notify_id)


@sql_wrapper
def delete_notification(notify_id):
    delete(Notification, notify_id)


@sql_wrapper
def get_xinge_notification(id):
    return get(XingeNotification, id)


@sql_wrapper
def upsert_xinge_notification(info, id=None):
    return upsert(XingeNotification, info, id)


@sql_wrapper
def list_xinge_notification(query_dct):
    return list_object(query_dct, XingeNotification)


@sql_wrapper
def delete_xinge_notification(id):
    delete(XingeNotification, id)


@sql_wrapper
def get_last_in_app_announcement(ts):
    return InAppAnnouncement.query.filter(InAppAnnouncement.start_ts <= ts). \
        filter(InAppAnnouncement.end_ts >= ts). \
        order_by(InAppAnnouncement.id.desc()).first()
